```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Netty TCP粘包和拆包问题解决方案</title>
    <link rel="stylesheet" href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css">
    <link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            background-color: #f8fafc;
            color: #1e293b;
        }
        .hero-gradient {
            background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%);
        }
        .code-block {
            background-color: #1e293b;
            border-radius: 0.5rem;
            box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
        }
        .code-header {
            background-color: #334155;
            border-top-left-radius: 0.5rem;
            border-top-right-radius: 0.5rem;
        }
        .solution-card:hover {
            transform: translateY(-4px);
            box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
        }
        .highlight {
            position: relative;
        }
        .highlight:after {
            content: '';
            position: absolute;
            bottom: 0;
            left: 0;
            width: 100%;
            height: 30%;
            background-color: rgba(79, 70, 229, 0.2);
            z-index: -1;
            transform: skewY(-1deg);
        }
    </style>
</head>
<body class="antialiased">
    <!-- Hero Section -->
    <section class="hero-gradient text-white py-20">
        <div class="container mx-auto px-6 lg:px-16">
            <div class="max-w-4xl mx-auto text-center">
                <h1 class="text-4xl md:text-5xl lg:text-6xl font-bold mb-6 font-serif">
                    Netty TCP粘包和拆包问题解决方案
                </h1>
                <p class="text-xl md:text-2xl opacity-90 mb-8 leading-relaxed">
                    探索高效网络通信的核心技术，解决TCP协议中的数据边界难题
                </p>
                <div class="inline-flex items-center space-x-2 text-indigo-200">
                    <i class="fas fa-network-wired text-lg"></i>
                    <span>网络编程</span>
                    <i class="fas fa-circle text-xs opacity-50"></i>
                    <i class="fas fa-code text-lg"></i>
                    <span>高性能IO</span>
                </div>
            </div>
        </div>
    </section>

    <!-- Main Content -->
    <div class="container mx-auto px-6 lg:px-16 py-16">
        <!-- Introduction -->
        <section class="max-w-4xl mx-auto mb-16">
            <div class="bg-white rounded-xl shadow-lg p-8 md:p-10">
                <h2 class="text-3xl font-bold mb-6 text-gray-800 highlight inline-block">
                    问题概述
                </h2>
                <p class="text-lg text-gray-700 leading-relaxed mb-6">
                    在Netty中，处理TCP的粘包和拆包问题是网络通信中的一个重要任务。TCP协议本身并不会在应用层区分数据包的边界，这就导致了粘包（多个数据包合并成一个）和拆包（一个数据包被拆分成多个）的问题。
                </p>
                
                <div class="grid md:grid-cols-2 gap-8 mt-10">
                    <div class="bg-indigo-50 p-6 rounded-lg border border-indigo-100">
                        <div class="flex items-center mb-4">
                            <div class="bg-indigo-100 p-3 rounded-full mr-4">
                                <i class="fas fa-layer-group text-indigo-600"></i>
                            </div>
                            <h3 class="text-xl font-bold text-gray-800">粘包问题</h3>
                        </div>
                        <p class="text-gray-700">
                            指的是多个消息被合并在一起发送到接收端，接收端无法正确区分这些消息的边界。
                        </p>
                    </div>
                    <div class="bg-pink-50 p-6 rounded-lg border border-pink-100">
                        <div class="flex items-center mb-4">
                            <div class="bg-pink-100 p-3 rounded-full mr-4">
                                <i class="fas fa-cut text-pink-600"></i>
                            </div>
                            <h3 class="text-xl font-bold text-gray-800">拆包问题</h3>
                        </div>
                        <p class="text-gray-700">
                            指的是一个消息被拆分成多个数据包发送到接收端，接收端需要重新组装这些数据包以还原原始消息。
                        </p>
                    </div>
                </div>
            </div>
        </section>

        <!-- Solution Overview -->
        <section class="max-w-4xl mx-auto mb-16">
            <h2 class="text-3xl font-bold mb-10 text-gray-800 highlight inline-block">
                Netty解决方案
            </h2>
            
            <!-- Solution Diagram -->
            <div class="bg-white rounded-xl shadow-lg p-6 mb-12">
                <div class="mermaid">
                    graph TD
                        A[TCP粘包拆包问题] --> B[定长消息]
                        A --> C[分隔符分隔]
                        A --> D[长度字段]
                        A --> E[自定义解码器]
                        B --> F[FixedLengthFrameDecoder]
                        C --> G[DelimiterBasedFrameDecoder]
                        D --> H[LengthFieldBasedFrameDecoder]
                        E --> I[ByteToMessageDecoder]
                </div>
            </div>

            <!-- Solution Cards -->
            <div class="grid md:grid-cols-2 gap-8">
                <!-- Fixed Length -->
                <div class="solution-card bg-white rounded-xl shadow-lg overflow-hidden transition-all duration-300">
                    <div class="p-6">
                        <div class="flex items-center mb-4">
                            <div class="bg-indigo-600 text-white p-2 rounded-lg mr-4">
                                <i class="fas fa-ruler-horizontal text-xl"></i>
                            </div>
                            <h3 class="text-2xl font-bold text-gray-800">定长消息</h3>
                        </div>
                        <p class="text-gray-700 mb-4">
                            对于每个消息都有固定的长度，可以简单地通过读取指定字节数的数据来解决粘包和拆包问题。
                        </p>
                        <div class="code-block">
                            <div class="code-header text-gray-300 px-4 py-2 flex items-center">
                                <div class="flex space-x-2 mr-4">
                                    <div class="w-3 h-3 rounded-full bg-red-500"></div>
                                    <div class="w-3 h-3 rounded-full bg-yellow-500"></div>
                                    <div class="w-3 h-3 rounded-full bg-green-500"></div>
                                </div>
                                <span>FixedLengthFrameDecoderDemo.java</span>
                            </div>
                            <pre class="text-gray-300 p-4 overflow-x-auto"><code>import io.netty.handler.codec.FixedLengthFrameDecoder;

public class FixedLengthFrameDecoderDemo {
    public static void main(String[] args) {
        // 定义每个消息的长度为 1024 字节
        int frameLength = 1024;
        FixedLengthFrameDecoder decoder = new FixedLengthFrameDecoder(frameLength);
        
        // 将 decoder 添加到 ChannelPipeline 中
        pipeline.addLast("decoder", decoder);
        pipeline.addLast("handler", new MyHandler());
    }
}</code></pre>
                        </div>
                    </div>
                </div>

                <!-- Delimiter Based -->
                <div class="solution-card bg-white rounded-xl shadow-lg overflow-hidden transition-all duration-300">
                    <div class="p-6">
                        <div class="flex items-center mb-4">
                            <div class="bg-green-600 text-white p-2 rounded-lg mr-4">
                                <i class="fas fa-slash text-xl"></i>
                            </div>
                            <h3 class="text-2xl font-bold text-gray-800">分隔符分隔</h3>
                        </div>
                        <p class="text-gray-700 mb-4">
                            对于使用特定分隔符（如换行符）分隔的消息，可以使用DelimiterBasedFrameDecoder类。
                        </p>
                        <div class="code-block">
                            <div class="code-header text-gray-300 px-4 py-2 flex items-center">
                                <div class="flex space-x-2 mr-4">
                                    <div class="w-3 h-3 rounded-full bg-red-500"></div>
                                    <div class="w-3 h-3 rounded-full bg-yellow-500"></div>
                                    <div class="w-3 h-3 rounded-full bg-green-500"></div>
                                </div>
                                <span>DelimiterBasedFrameDecoderDemo.java</span>
                            </div>
                            <pre class="text-gray-300 p-4 overflow-x-auto"><code>import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.buffer.Unpooled;

public class DelimiterBasedFrameDecoderDemo {
    public static void main(String[] args) {
        // 定义消息分隔符
        ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes());
        
        // 使用分隔符解码器
        DelimiterBasedFrameDecoder decoder = new DelimiterBasedFrameDecoder(8192, delimiter);
        
        // 将 decoder 添加到 ChannelPipeline 中
        pipeline.addLast("decoder", decoder);
        pipeline.addLast("encoder", new StringEncoder());
        pipeline.addLast("handler", new MyHandler());
    }
}</code></pre>
                        </div>
                    </div>
                </div>

                <!-- Length Field -->
                <div class="solution-card bg-white rounded-xl shadow-lg overflow-hidden transition-all duration-300">
                    <div class="p-6">
                        <div class="flex items-center mb-4">
                            <div class="bg-purple-600 text-white p-2 rounded-lg mr-4">
                                <i class="fas fa-text-width text-xl"></i>
                            </div>
                            <h3 class="text-2xl font-bold text-gray-800">长度字段</h3>
                        </div>
                        <p class="text-gray-700 mb-4">
                            如果消息中包含长度字段（例如，前4个字节表示消息的长度），可以使用LengthFieldBasedFrameDecoder类。
                        </p>
                        <div class="code-block">
                            <div class="code-header text-gray-300 px-4 py-2 flex items-center">
                                <div class="flex space-x-2 mr-4">
                                    <div class="w-3 h-3 rounded-full bg-red-500"></div>
                                    <div class="w-3 h-3 rounded-full bg-yellow-500"></div>
                                    <div class="w-3 h-3 rounded-full bg-green-500"></div>
                                </div>
                                <span>LengthFieldBasedFrameDecoderDemo.java</span>
                            </div>
                            <pre class="text-gray-300 p-4 overflow-x-auto"><code>import io.netty.handler.codec.LengthFieldBasedFrameDecoder;

public class LengthFieldBasedFrameDecoderDemo {
    public static void main(String[] args) {
        // 定义长度字段参数
        int maxFrameLength = 1024;
        int lengthFieldOffset = 0;
        int lengthFieldLength = 4;
        int lengthAdjustment = 0;
        int initialBytesToStrip = 0;
        
        LengthFieldBasedFrameDecoder decoder = new LengthFieldBasedFrameDecoder(
            maxFrameLength, lengthFieldOffset, lengthFieldLength, 
            lengthAdjustment, initialBytesToStrip
        );
        
        // 将 decoder 添加到 ChannelPipeline 中
        pipeline.addLast("decoder", decoder);
        pipeline.addLast("handler", new MyHandler());
    }
}</code></pre>
                        </div>
                    </div>
                </div>

                <!-- Custom Decoder -->
                <div class="solution-card bg-white rounded-xl shadow-lg overflow-hidden transition-all duration-300">
                    <div class="p-6">
                        <div class="flex items-center mb-4">
                            <div class="bg-red-600 text-white p-2 rounded-lg mr-4">
                                <i class="fas fa-code text-xl"></i>
                            </div>
                            <h3 class="text-2xl font-bold text-gray-800">自定义解码器</h3>
                        </div>
                        <p class="text-gray-700 mb-4">
                            对于更复杂的协议，可以自定义解码器来处理粘包和拆包问题。
                        </p>
                        <div class="code-block">
                            <div class="code-header text-gray-300 px-4 py-2 flex items-center">
                                <div class="flex space-x-2 mr-4">
                                    <div class="w-3 h-3 rounded-full bg-red-500"></div>
                                    <div class="w-3 h-3 rounded-full bg-yellow-500"></div>
                                    <div class="w-3 h-3 rounded-full bg-green-500"></div>
                                </div>
                                <span>CustomFrameDecoder.java</span>
                            </div>
                            <pre class="text-gray-300 p-4 overflow-x-auto"><code>import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

public class CustomFrameDecoder extends ByteToMessageDecoder {
    @Override
    protected void decode(ChannelHandlerContext ctx, 
                         ByteBuf in, List&lt;Object&gt; out) throws Exception {
        // 自定义解码逻辑
        if (in.readableBytes() &lt; 4) {
            return; // 等待更多数据
        }

        in.markReaderIndex(); // 标记读索引
        int length = in.readInt(); // 读取消息长度
        
        if (in.readableBytes() &lt; length) {
            in.resetReaderIndex(); // 重置读索引
            return; // 等待更多数据
        }
        
        ByteBuf frame = in.readBytes(length); // 读取消息
        out.add(frame); // 添加到解码器输出列表
    }
}</code></pre>
                        </div>
                    </div>
                </div>
            </div>
        </section>

        <!-- Comparison Table -->
        <section class="max-w-4xl mx-auto mb-16">
            <div class="bg-white rounded-xl shadow-lg p-8">
                <h2 class="text-3xl font-bold mb-6 text-gray-800 highlight inline-block">
                    方案对比
                </h2>
                <div class="overflow-x-auto">
                    <table class="w-full">
                        <thead>
                            <tr class="bg-gray-100">
                                <th class="py-3 px-4 text-left font-semibold text-gray-700">方案</th>
                                <th class="py-3 px-4 text-left font-semibold text-gray-700">适用场景</th>
                                <th class="py-3 px-4 text-left font-semibold text-gray-700">优点</th>
                                <th class="py-3 px-4 text-left font-semibold text-gray-700">缺点</th>
                            </tr>
                        </thead>
                        <tbody class="divide-y divide-gray-200">
                            <tr>
                                <td class="py-3 px-4 font-medium">定长消息</td>
                                <td class="py-3 px-4 text-gray-700">固定长度的消息协议</td>
                                <td class="py-3 px-4 text-gray-700">实现简单，解码效率高</td>
                                <td class="py-3 px-4 text-gray-700">不适用于变长消息</td>
                            </tr>
                            <tr>
                                <td class="py-3 px-4 font-medium">分隔符分隔</td>
                                <td class="py-3 px-4 text-gray-700">文本协议或以特定字符分隔的消息</td>
                                <td class="py-3 px-4 text-gray-700">实现简单，适用于文本协议</td>
                                <td class="py-3 px-4 text-gray-700">需要转义分隔符，性能稍差</td>
                            </tr>
                            <tr>
                                <td class="py-3 px-4 font-medium">长度字段</td>
                                <td class="py-3 px-4 text-gray-700">包含长度字段的二进制协议</td>
                                <td class="py-3 px-4 text-gray-700">高效灵活，适用于复杂协议</td>
                                <td class="py-3 px-4 text-gray-700">协议设计需要包含长度字段</td>
                            </tr>
                            <tr>
                                <td class="py-3 px-4 font-medium">自定义解码器</td>
                                <td class="py-3 px-4 text-gray-700">特殊或复杂协议</td>
                                <td class="py-3 px-4 text-gray-700">完全控制，最灵活</td>
                                <td class="py-3 px-4 text-gray-700">实现复杂，维护成本高</td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </section>

        <!-- Best Practices -->
        <section class="max-w-4xl mx-auto">
            <div class="bg-white rounded-xl shadow-lg p-8">
                <h2 class="text-3xl font-bold mb-6 text-gray-800 highlight inline-block">
                    最佳实践建议
                </h2>
                <div class="space-y-6">
                    <div class="flex items-start">
                        <div class="bg-indigo-100 p-2 rounded-lg mr-4 mt-1">
                            <i class="fas fa-lightbulb text-indigo-600"></i>
                        </div>
                        <div>
                            <h4 class="text-xl font-semibold text-gray-800 mb-2">选择适合协议的解码器</h4>
                            <p class="text-gray-700">
                                根据您的协议特点选择最合适的解码器。对于简单文本协议，分隔符解码器可能足够；对于二进制协议，长度字段解码器通常是更好的选择。
                            </p>
                        </div>
                    </div>
                    <div class="flex items-start">
                        <div class="bg-indigo-100 p-2 rounded-lg mr-4 mt-1">
                            <i class="fas fa-shield-alt text-indigo-600"></i>
                        </div>
                        <div>
                            <h4 class="text-xl font-semibold text-gray-800 mb-2">设置合理的消息长度限制</h4>
                            <p class="text-gray-700">
                                在使用长度字段解码器时，务必设置合理的maxFrameLength以防止恶意攻击或内存溢出。同时考虑消息体的最大可能大小。
                            </p>
                        </div>
                    </div>
                    <div class="flex items-start">
                        <div class="bg-indigo-100 p-2 rounded-lg mr-4 mt-1">
                            <i class="fas fa-tachometer-alt text-indigo-600"></i>
                        </div>
                        <div>
                            <h4 class="text-xl font-semibold text-gray-800 mb-2">性能考虑</h4>
                            <p class="text-gray-700">
                                定长解码器性能最优，其次是长度字段解码器。自定义解码器性能取决于实现方式。在性能关键场景下，应进行基准测试。
                            </p>
                        </div>
                    </div>
                    <div class="flex items-start">
                        <div class="bg-indigo-100 p-2 rounded-lg mr-4 mt-1">
                            <i class="fas fa-exchange-alt text-indigo-600"></i>
                        </div>
                        <div>
                            <h4 class="text-xl font-semibold text-gray-800 mb-2">与编码器配合使用</h4>
                            <p class="text-gray-700">
                                确保发送端和接收端使用相同的编码/解码策略。例如，如果使用长度字段解码器，发送端应在消息前添加长度字段。
                            </p>
                        </div>
                    </div>
                </div>
            </div>
        </section>
    </div>

    <!-- Footer -->
    <footer class="bg-gray-900 text-gray-300 py-12">
        <div class="container mx-auto px-6">
            <div class="max-w-4xl mx-auto flex flex-col items-center">
                <div class="text-xl font-medium mb-4">技术小馆</div>
                <a href="http://www.yuque.com/jtostring" class="text-indigo-400 hover:text-indigo-300 transition-colors duration-200">
                    <i class="fas fa-link mr-2"></i>
                    http://www.yuque.com/jtostring
                </a>
            </div>
        </div>
    </footer>

    <script>
        mermaid.initialize({
            startOnLoad: true,
            theme: 'default',
            flowchart: {
                useMaxWidth: false,
                htmlLabels: true,
                curve: 'basis'
            }
        });
    </script>
</body>
</html>
```